﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Storage;
using Storage.EntityModels;
using System.Data.Linq;
using Stats.Objects;

namespace Stats
{
    /// <summary>
    /// This class contains the methods used to retrieve the user feedback from the db. There are many types of user feedbacks such as
    /// AsDriverFeedback, AsPassengerFeedback and GeneralFeedback. There is also a method to retrieve all the feedbacks left for a user which returns
    /// a List of Feedback objects.
    /// </summary>
    static class GetFeedbackModule
    {
        /// <summary>
        /// This method is called by groupware and contains operations to retrieve user driver feedback and returns 
        /// an AsDriverrFeedback object
        /// </summary>
        /// <param name="userID">UserID to view the feedback as driver</param>
        /// <returns>AsDriverFeedback object</returns>
        public static AsDriverFeedback getAsDriverFeedbackOperation(int userID)
        {
            AsDriverFeedback fdb;

            try
            {
                TripLoaDataContext db = Storage.StorageManager.Instance.Entities;

                var resultsTable =
                    from d in db.UserFeedbacks
                    where d.UserId == userID
                    select d;

                var userDrFeedback = resultsTable.First();

                fdb = new AsDriverFeedback(userID, userDrFeedback.AsDriverAVGVote, userDrFeedback.AsDriverAVGPunctuality,
                                            userDrFeedback.AsDriverAVGReliability, userDrFeedback.AsDriverAVGKindness, userDrFeedback.NumberOfJourneysWithFeedbackAsDriver);

            }
            catch (InvalidOperationException) { fdb = new AsDriverFeedback(0, 0, 0, 0, 0, 0); }
            catch (TypeInitializationException) { fdb = new AsDriverFeedback(0, 0, 0, 0, 0, 0); }
            catch (NullReferenceException) { fdb = new AsDriverFeedback(0, 0, 0, 0, 0, 0); }
            catch (System.Data.SqlClient.SqlException) { fdb = new AsDriverFeedback(0, 0, 0, 0, 0, 0); }

            return fdb;
        }
        
        /// <summary>
        /// This method is called by groupware and contains operations to retrieve user passenger feedback and returns 
        /// an AsPassengerFeedback object
        /// </summary>
        /// <param name="userID">UserID to view the feedback as passenger</param>
        /// <returns>AsPAssengerFeedback object</returns>
        public static AsPassengerFeedback getAsPassengerFeedbackOperation(int userID)
        {
            AsPassengerFeedback fdb;

            try
            {
                TripLoaDataContext db = Storage.StorageManager.Instance.Entities;

                var userFeedbacksEntry =
                     (from userFeedbacks in db.UserFeedbacks
                     where userFeedbacks.UserId == userID
                     select userFeedbacks).First();

                fdb = new AsPassengerFeedback(userID, userFeedbacksEntry.AsPassengerAVGVote, userFeedbacksEntry.AsPassengerAVGPunctuality,
                                                userFeedbacksEntry.AsPassengerAVGReliability,userFeedbacksEntry.NumberOfJourneysWithFeedbackAsPassenger);
            }
            catch (InvalidOperationException) { fdb = new AsPassengerFeedback(0, 0, 0, 0, 0); }
            catch (TypeInitializationException) { fdb = new AsPassengerFeedback(0, 0, 0, 0, 0); }
            catch (NullReferenceException) { fdb = new AsPassengerFeedback(0, 0, 0, 0, 0); }
            catch (System.Data.SqlClient.SqlException) { fdb = new AsPassengerFeedback(0, 0, 0, 0, 0); }

            return fdb;
        }
        
        /// <summary>
        /// This method is called by groupware and contains operations to retrieve user general feedback and returns 
        /// an GeneralFeedback object
        /// </summary>
        /// <param name="userID"></param>
        /// <returns></returns>
        public static GeneralFeedback getGeneralFeedbackOperation(int userID)
        {
            double general_vote = 0;
            double general_punct = 0;
            double general_reliab = 0;

            try
            {
                TripLoaDataContext db = Storage.StorageManager.Instance.Entities;

                var userFeedbacksEntry =
                            (from userFeedbacksEntries in db.UserFeedbacks
                             where userFeedbacksEntries.UserId == userID
                             select userFeedbacksEntries).First();

                int numFeedbackAsDriver = userFeedbacksEntry.NumberOfJourneysWithFeedbackAsDriver;
                int numFeedbackAsPassenger = userFeedbacksEntry.NumberOfJourneysWithFeedbackAsPassenger;

                if (numFeedbackAsDriver + numFeedbackAsPassenger != 0)
                {
                    general_vote = (userFeedbacksEntry.AsDriverAVGVote * numFeedbackAsDriver + userFeedbacksEntry.AsPassengerAVGVote * numFeedbackAsPassenger) / (numFeedbackAsDriver + numFeedbackAsPassenger);
                    general_punct = (userFeedbacksEntry.AsDriverAVGPunctuality * numFeedbackAsDriver + userFeedbacksEntry.AsPassengerAVGPunctuality * numFeedbackAsPassenger) / (numFeedbackAsDriver + numFeedbackAsPassenger);
                    general_reliab = (userFeedbacksEntry.AsDriverAVGReliability * numFeedbackAsDriver + userFeedbacksEntry.AsPassengerAVGReliability * numFeedbackAsPassenger) / (numFeedbackAsDriver + numFeedbackAsPassenger);
                }
            }
            catch (InvalidOperationException) { userID = 0; general_vote = 0; general_punct = 0; general_reliab = 0; }
            catch (TypeInitializationException) { userID = 0; general_vote = 0; general_punct = 0; general_reliab = 0; }
            catch (NullReferenceException) { userID = 0; general_vote = 0; general_punct = 0; general_reliab = 0; }
            catch (System.Data.SqlClient.SqlException) { userID = 0; general_vote = 0; general_punct = 0; general_reliab = 0; }

            GeneralFeedback fdb = new GeneralFeedback(userID, general_vote, general_punct, general_reliab);

            return fdb;
        }
        
        /// <summary>
        /// This method is called by anonymizer and contains operations to retrieve TriploA feedback list for the user specified..returns 
        /// a Feedback List
        /// </summary>
        /// <param name="userID">UserID</param>
        /// <returns>list of feedback objects</returns>
        public static List<Feedback> getUserFeedbackListOperation(int userID)
        {
            List<Feedback> feedbackList = new List<Feedback>();

            try
            {
                TripLoaDataContext db = Storage.StorageManager.Instance.Entities;

                var psnFeedbackEntries =
                     from psnEntries in db.PassengerFeedbacks
                     where psnEntries.ReceiverUserId == userID
                     select psnEntries;

                var drvFeedbackEntries =
                     from drvEntries in db.DriverFeedbacks
                     where drvEntries.ReceiverUserId == userID
                     select drvEntries;

                int numFeedback = drvFeedbackEntries.Count() + psnFeedbackEntries.Count();

                if (numFeedback > 0)
                {
                    TripProperties tripInfo;

                    int? senderID;
                    string senderUsername;
                    string commentLeft;

                    foreach (var fdbDrv in drvFeedbackEntries)
                    {
                        tripInfo = AuxTripMethods.getTripProperties(fdbDrv.TripId);

                        if (tripInfo != null)
                        {
                            senderID = fdbDrv.SenderUserId;
                            commentLeft = fdbDrv.Comment;

                            //if (senderID == null) 
                            //{      senderID = StatsModule.UnregisteredUserID;
                            //       senderUsername = StatsModule.UnregisteredUsername;
                            //}
                            
                            //else { senderUsername = AuxUserMethods.getUserUsername((int)senderID); }

                            senderUsername = AuxUserMethods.getUserUsername((int)senderID);

                            //if (commentLeft == null) commentLeft = StatsModule.noCommentLeftString;

                            Feedback drvFeedback = new Feedback(true, fdbDrv.TripId, tripInfo.DepartureDate, fdbDrv.ReceiverUserId, AuxUserMethods.getUserUsername((int)fdbDrv.ReceiverUserId), (int)senderID,
                                    senderUsername, (int)fdbDrv.GenericVote, (int)fdbDrv.PunctualityVote, (int)fdbDrv.ReliabilityVote, (int)fdbDrv.PermissivenessVote,
                                    commentLeft, tripInfo.OriginCity, tripInfo.OriginAddress, tripInfo.DestinationCity, tripInfo.DestinationAddress);

                            feedbackList.Add(drvFeedback);
                        }
                    }

                    foreach (var fdbPsn in psnFeedbackEntries)
                    {

                        tripInfo = AuxTripMethods.getTripProperties(fdbPsn.TripId);

                        if (tripInfo != null)
                        {
                            senderID = fdbPsn.SenderUserId;
                            commentLeft = fdbPsn.Comment;
                            senderUsername = AuxUserMethods.getUserUsername((int)senderID);

                            //if (senderID == null)
                            //{   senderID = StatsModule.UnregisteredUserID;
                            //    senderUsername = StatsModule.UnregisteredUsername;
                            //}
                            
                            //else { senderUsername = AuxUserMethods.getUserUsername((int)senderID); }

                            //if (commentLeft == null) commentLeft = StatsModule.noCommentLeftString;

                            Feedback psnFeedback = new Feedback(false, fdbPsn.TripId, tripInfo.DepartureDate, fdbPsn.ReceiverUserId, AuxUserMethods.getUserUsername((int)fdbPsn.ReceiverUserId), (int)senderID, senderUsername, (int)fdbPsn.GenericVote,
                                    (int)fdbPsn.PunctualityVote, (int)fdbPsn.ReliabilityVote, 0, commentLeft, tripInfo.OriginCity, tripInfo.OriginAddress, tripInfo.DestinationCity, tripInfo.DestinationAddress);

                            feedbackList.Add(psnFeedback);
                        }
                    }
                }

            }
            catch (InvalidOperationException) { feedbackList = new List<Feedback>(); }
            catch (TypeInitializationException) { feedbackList = new List<Feedback>(); }
            catch (System.Data.SqlClient.SqlException) { feedbackList = new List<Feedback>(); }
            catch (NullReferenceException) { feedbackList = new List<Feedback>(); }

            return feedbackList;
        }
        

    }
}
